home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / storage / smgr / mm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  12.4 KB  |  599 lines

  1. /*
  2.  *  mm.c -- main memory storage manager
  3.  *
  4.  *    This code manages relations that reside in (presumably stable)
  5.  *    main memory.
  6.  */
  7.  
  8. #include "tmp/c.h"
  9. #include "tmp/postgres.h"
  10.  
  11. #ifdef MAIN_MEMORY
  12.  
  13. #include <math.h>
  14. #include "machine.h"
  15. #include "storage/ipc.h"
  16. #include "storage/ipci.h"
  17. #include "storage/smgr.h"
  18. #include "storage/block.h"
  19. #include "storage/shmem.h"
  20. #include "storage/spin.h"
  21.  
  22. #include "utils/hsearch.h"
  23. #include "utils/rel.h"
  24. #include "utils/log.h"
  25.  
  26. RcsId("$Header: /private/postgres/src/storage/smgr/RCS/mm.c,v 1.8 1992/02/24 13:30:22 mao Exp $");
  27.  
  28. /*
  29.  *  MMCacheTag -- Unique triplet for blocks stored by the main memory
  30.  *          storage manager.
  31.  */
  32.  
  33. typedef struct MMCacheTag {
  34.     ObjectId        mmct_dbid;
  35.     ObjectId        mmct_relid;
  36.     BlockNumber        mmct_blkno;
  37. } MMCacheTag;
  38.  
  39. /*
  40.  *  Shared-memory hash table for main memory relations contains
  41.  *  entries of this form.
  42.  */
  43.  
  44. typedef struct MMHashEntry {
  45.     MMCacheTag        mmhe_tag;
  46.     int            mmhe_bufno;
  47. } MMHashEntry;
  48.  
  49. /*
  50.  * MMRelTag -- Unique identifier for each relation that is stored in the
  51.  *                main-memory storage manager.
  52.  */
  53.  
  54. typedef struct MMRelTag {
  55.     ObjectId        mmrt_dbid;
  56.     ObjectId        mmrt_relid;
  57. } MMRelTag;
  58.  
  59. /*
  60.  *  Shared-memory hash table for # blocks in main memory relations contains
  61.  *  entries of this form.
  62.  */
  63.  
  64. typedef struct MMRelHashEntry {
  65.     MMRelTag        mmrhe_tag;
  66.     int            mmrhe_nblocks;
  67. } MMRelHashEntry;
  68.  
  69. #define MMNBUFFERS    10
  70. #define MMNRELATIONS    2
  71.  
  72. SPINLOCK    MMCacheLock;
  73. extern bool    IsPostmaster;
  74. extern ObjectId    MyDatabaseId;
  75.  
  76. static int        *MMCurTop;
  77. static int        *MMCurRelno;
  78. static MMCacheTag    *MMBlockTags;
  79. static char        *MMBlockCache;
  80. static HTAB        *MMCacheHT;
  81. static HTAB        *MMRelCacheHT;
  82.  
  83. int
  84. mminit()
  85. {
  86.     char *mmcacheblk;
  87.     int mmsize;
  88.     bool found;
  89.     HASHCTL info;
  90.  
  91.     SpinAcquire(MMCacheLock);
  92.  
  93.     mmsize = (BLCKSZ * MMNBUFFERS) + sizeof(*MMCurTop) + sizeof(*MMCurRelno);
  94.     mmsize += (MMNBUFFERS * sizeof(MMCacheTag));
  95.     mmcacheblk = (char *) ShmemInitStruct("Main memory smgr", mmsize, &found);
  96.  
  97.     if (mmcacheblk == (char *) NULL) {
  98.     SpinRelease(MMCacheLock);
  99.     return (SM_FAIL);
  100.     }
  101.  
  102.     info.keysize = sizeof(MMCacheTag);
  103.     info.datasize = sizeof(int);
  104.     info.hash = tag_hash;
  105.  
  106.     MMCacheHT = (HTAB *) ShmemInitHash("Main memory store HT",
  107.                     MMNBUFFERS, MMNBUFFERS,
  108.                     &info, (HASH_ELEM|HASH_FUNCTION));
  109.  
  110.     if (MMCacheHT == (HTAB *) NULL) {
  111.     SpinRelease(MMCacheLock);
  112.     return (SM_FAIL);
  113.     }
  114.  
  115.     info.keysize = sizeof(MMRelTag);
  116.     info.datasize = sizeof(int);
  117.     info.hash = tag_hash;
  118.  
  119.     MMRelCacheHT = (HTAB *) ShmemInitHash("Main memory rel HT",
  120.                       MMNRELATIONS, MMNRELATIONS,
  121.                       &info, (HASH_ELEM|HASH_FUNCTION));
  122.  
  123.     if (MMRelCacheHT == (HTAB *) NULL) {
  124.     SpinRelease(MMCacheLock);
  125.     return (SM_FAIL);
  126.     }
  127.  
  128.     if (IsPostmaster) {
  129.     bzero(mmcacheblk, mmsize);
  130.     SpinRelease(MMCacheLock);
  131.     return (SM_SUCCESS);
  132.     }
  133.  
  134.     SpinRelease(MMCacheLock);
  135.  
  136.     MMCurTop = (int *) mmcacheblk;
  137.     mmcacheblk += sizeof(int);
  138.     MMCurRelno = (int *) mmcacheblk;
  139.     mmcacheblk += sizeof(int);
  140.     MMBlockTags = (MMCacheTag *) mmcacheblk;
  141.     mmcacheblk += (MMNBUFFERS * sizeof(MMCacheTag));
  142.     MMBlockCache = mmcacheblk;
  143.  
  144.     return (SM_SUCCESS);
  145. }
  146.  
  147. int
  148. mmshutdown()
  149. {
  150.     return (SM_SUCCESS);
  151. }
  152.  
  153. int
  154. mmcreate(reln)
  155.     Relation reln;
  156. {
  157.     MMRelHashEntry *entry;
  158.     bool found;
  159.     MMRelTag tag;
  160.  
  161.     SpinAcquire(MMCacheLock);
  162.  
  163.     if (*MMCurRelno == MMNRELATIONS) {
  164.     SpinRelease(MMCacheLock);
  165.     return (SM_FAIL);
  166.     }
  167.  
  168.     (*MMCurRelno)++;
  169.  
  170.     tag.mmrt_relid = reln->rd_id;
  171.     if (reln->rd_rel->relisshared)
  172.     tag.mmrt_dbid = (ObjectId) 0;
  173.     else
  174.     tag.mmrt_dbid = MyDatabaseId;
  175.  
  176.     entry = (MMRelHashEntry *) hash_search(MMRelCacheHT,
  177.                        (char *) &tag, HASH_ENTER, &found);
  178.  
  179.     if (entry == (MMRelHashEntry *) NULL) {
  180.     SpinRelease(MMCacheLock);
  181.     elog(FATAL, "main memory storage mgr rel cache hash table corrupt");
  182.     }
  183.  
  184.     if (found) {
  185.     /* already exists */
  186.     SpinRelease(MMCacheLock);
  187.     return (SM_FAIL);
  188.     }
  189.  
  190.     entry->mmrhe_nblocks = 0;
  191.  
  192.     SpinRelease(MMCacheLock);
  193.  
  194.     return (SM_SUCCESS);
  195. }
  196.  
  197. /*
  198.  *  mmunlink() -- Unlink a relation.
  199.  */
  200.  
  201. int
  202. mmunlink(reln)
  203.     Relation reln;
  204. {
  205.     int i;
  206.     ObjectId reldbid;
  207.     MMHashEntry *entry;
  208.     MMRelHashEntry *rentry;
  209.     bool found;
  210.     MMRelTag rtag;
  211.  
  212.     if (reln->rd_rel->relisshared)
  213.     reldbid = (ObjectId) 0;
  214.     else
  215.     reldbid = MyDatabaseId;
  216.  
  217.     SpinAcquire(MMCacheLock);
  218.  
  219.     for (i = 0; i < MMNBUFFERS; i++) {
  220.     if (MMBlockTags[i].mmct_dbid == reldbid
  221.         && MMBlockTags[i].mmct_relid == reln->rd_id) {
  222.         entry = (MMHashEntry *) hash_search(MMCacheHT,
  223.                         (char *) &MMBlockTags[i],
  224.                          HASH_REMOVE, &found);
  225.         if (entry == (MMHashEntry *) NULL || !found) {
  226.         SpinRelease(MMCacheLock);
  227.         elog(FATAL, "mmunlink: cache hash table corrupted");
  228.         }
  229.         MMBlockTags[i].mmct_dbid = (ObjectId) 0;
  230.         MMBlockTags[i].mmct_relid = (ObjectId) 0;
  231.         MMBlockTags[i].mmct_blkno = (BlockNumber) 0;
  232.     }
  233.     }
  234.     rtag.mmrt_dbid = reldbid;
  235.     rtag.mmrt_relid = reln->rd_id;
  236.  
  237.     rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
  238.                         HASH_REMOVE, &found);
  239.  
  240.     if (rentry == (MMRelHashEntry *) NULL || !found) {
  241.     SpinRelease(MMCacheLock);
  242.     elog(FATAL, "mmunlink: rel cache hash table corrupted");
  243.     }
  244.  
  245.     (*MMCurRelno)--;
  246.  
  247.     SpinRelease(MMCacheLock);
  248. }
  249.  
  250. /*
  251.  *  mmextend() -- Add a block to the specified relation.
  252.  *
  253.  *    This routine returns SM_FAIL or SM_SUCCESS, with errno set as
  254.  *    appropriate.
  255.  */
  256.  
  257. int
  258. mmextend(reln, buffer)
  259.     Relation reln;
  260.     char *buffer;
  261. {
  262.     MMRelHashEntry *rentry;
  263.     MMHashEntry *entry;
  264.     int i;
  265.     ObjectId reldbid;
  266.     int offset;
  267.     bool found;
  268.     MMRelTag rtag;
  269.     MMCacheTag tag;
  270.  
  271.     if (reln->rd_rel->relisshared)
  272.     reldbid = (ObjectId) 0;
  273.     else
  274.     reldbid = MyDatabaseId;
  275.  
  276.     tag.mmct_dbid = rtag.mmrt_dbid = reldbid;
  277.     tag.mmct_relid = rtag.mmrt_relid = reln->rd_id;
  278.  
  279.     SpinAcquire(MMCacheLock);
  280.  
  281.     if (*MMCurTop == MMNBUFFERS) {
  282.     for (i = 0; i < MMNBUFFERS; i++) {
  283.         if (MMBlockTags[i].mmct_dbid == 0 && MMBlockTags[i].mmct_relid == 0)
  284.         break;
  285.     }
  286.     if (i == MMNBUFFERS) {
  287.         SpinRelease(MMCacheLock);
  288.         return (SM_FAIL);
  289.     }
  290.     } else {
  291.     i = *MMCurTop;
  292.     (*MMCurTop)++;
  293.     }
  294.  
  295.     rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
  296.                         HASH_FIND, &found);
  297.     if (rentry == (MMRelHashEntry *) NULL || !found) {
  298.     SpinRelease(MMCacheLock);
  299.     elog(FATAL, "mmextend: rel cache hash table corrupt");
  300.     }
  301.  
  302.     tag.mmct_blkno = rentry->mmrhe_nblocks;
  303.  
  304.     entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
  305.                     HASH_ENTER, &found);
  306.     if (entry == (MMHashEntry *) NULL || found) {
  307.     SpinRelease(MMCacheLock);
  308.     elog(FATAL, "mmextend: cache hash table corrupt");
  309.     }
  310.  
  311.     entry->mmhe_bufno = i;
  312.     MMBlockTags[i].mmct_dbid = reldbid;
  313.     MMBlockTags[i].mmct_relid = reln->rd_id;
  314.     MMBlockTags[i].mmct_blkno = rentry->mmrhe_nblocks;
  315.  
  316.     /* page numbers are zero-based, so we increment this at the end */
  317.     (rentry->mmrhe_nblocks)++;
  318.  
  319.     /* write the extended page */
  320.     offset = (i * BLCKSZ);
  321.     bcopy(buffer, &(MMBlockCache[offset]), BLCKSZ);
  322.  
  323.     SpinRelease(MMCacheLock);
  324.  
  325.     return (SM_SUCCESS);
  326. }
  327.  
  328. /*
  329.  *  mmopen() -- Open the specified relation.
  330.  */
  331.  
  332. int
  333. mmopen(reln)
  334.     Relation reln;
  335. {
  336.     /* automatically successful */
  337.     return (0);
  338. }
  339.  
  340. /*
  341.  *  mmclose() -- Close the specified relation.
  342.  *
  343.  *    Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
  344.  */
  345.  
  346. int
  347. mmclose(reln)
  348.     Relation reln;
  349. {
  350.     /* automatically successful */
  351.     return (SM_SUCCESS);
  352. }
  353.  
  354. /*
  355.  *  mmread() -- Read the specified block from a relation.
  356.  *
  357.  *    Returns SM_SUCCESS or SM_FAIL.
  358.  */
  359.  
  360. int
  361. mmread(reln, blocknum, buffer)
  362.     Relation reln;
  363.     BlockNumber blocknum;
  364.     char *buffer;
  365. {
  366.     MMHashEntry *entry;
  367.     bool found;
  368.     int offset;
  369.     MMCacheTag tag;
  370.  
  371.     if (reln->rd_rel->relisshared)
  372.     tag.mmct_dbid = (ObjectId) 0;
  373.     else
  374.     tag.mmct_dbid = MyDatabaseId;
  375.  
  376.     tag.mmct_relid = reln->rd_id;
  377.     tag.mmct_blkno = blocknum;
  378.  
  379.     SpinAcquire(MMCacheLock);
  380.     entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
  381.                     HASH_FIND, &found);
  382.  
  383.     if (entry == (MMHashEntry *) NULL) {
  384.     SpinRelease(MMCacheLock);
  385.     elog(FATAL, "mmread: hash table corrupt");
  386.     }
  387.  
  388.     if (!found) {
  389.     /* reading nonexistent pages is defined to fill them with zeroes */
  390.     SpinRelease(MMCacheLock);
  391.     bzero(buffer, BLCKSZ);
  392.     return (SM_SUCCESS);
  393.     }
  394.  
  395.     offset = (entry->mmhe_bufno * BLCKSZ);
  396.     bcopy(&MMBlockCache[offset], buffer, BLCKSZ);
  397.  
  398.     SpinRelease(MMCacheLock);
  399.  
  400.     return (SM_SUCCESS);
  401. }
  402.  
  403. /*
  404.  *  mmwrite() -- Write the supplied block at the appropriate location.
  405.  *
  406.  *    Returns SM_SUCCESS or SM_FAIL.
  407.  */
  408.  
  409. int
  410. mmwrite(reln, blocknum, buffer)
  411.     Relation reln;
  412.     BlockNumber blocknum;
  413.     char *buffer;
  414. {
  415.     MMHashEntry *entry;
  416.     bool found;
  417.     int offset;
  418.     MMCacheTag tag;
  419.  
  420.     if (reln->rd_rel->relisshared)
  421.     tag.mmct_dbid = (ObjectId) 0;
  422.     else
  423.     tag.mmct_dbid = MyDatabaseId;
  424.  
  425.     tag.mmct_relid = reln->rd_id;
  426.     tag.mmct_blkno = blocknum;
  427.  
  428.     SpinAcquire(MMCacheLock);
  429.     entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
  430.                     HASH_FIND, &found);
  431.  
  432.     if (entry == (MMHashEntry *) NULL) {
  433.     SpinRelease(MMCacheLock);
  434.     elog(FATAL, "mmread: hash table corrupt");
  435.     }
  436.  
  437.     if (!found) {
  438.     SpinRelease(MMCacheLock);
  439.     elog(FATAL, "mmwrite: hash table missing requested page");
  440.     }
  441.  
  442.     offset = (entry->mmhe_bufno * BLCKSZ);
  443.     bcopy(buffer, &MMBlockCache[offset], BLCKSZ);
  444.  
  445.     SpinRelease(MMCacheLock);
  446.  
  447.     return (SM_SUCCESS);
  448. }
  449.  
  450. /*
  451.  *  mmflush() -- Synchronously write a block to stable storage.
  452.  *
  453.  *    For main-memory relations, this is exactly equivalent to mmwrite().
  454.  */
  455.  
  456. int
  457. mmflush(reln, blocknum, buffer)
  458.     Relation reln;
  459.     BlockNumber blocknum;
  460.     char *buffer;
  461. {
  462.     return (mmwrite(reln, blocknum, buffer));
  463. }
  464.  
  465. /*
  466.  *  mmblindwrt() -- Write a block to stable storage blind.
  467.  *
  468.  *    We have to be able to do this using only the name and OID of
  469.  *    the database and relation in which the block belongs.
  470.  */
  471.  
  472. int
  473. mmblindwrt(dbstr, relstr, dbid, relid, blkno, buffer)
  474.     char *dbstr;
  475.     char *relstr;
  476.     OID dbid;
  477.     OID relid;
  478.     BlockNumber blkno;
  479.     char *buffer;
  480. {
  481.     return (SM_FAIL);
  482. }
  483.  
  484. /*
  485.  *  mmnblocks() -- Get the number of blocks stored in a relation.
  486.  *
  487.  *    Returns # of blocks or -1 on error.
  488.  */
  489.  
  490. int
  491. mmnblocks(reln)
  492.     Relation reln;
  493. {
  494.     MMRelTag rtag;
  495.     MMRelHashEntry *rentry;
  496.     bool found;
  497.     int nblocks;
  498.  
  499.     if (reln->rd_rel->relisshared)
  500.     rtag.mmrt_dbid = (ObjectId) 0;
  501.     else
  502.     rtag.mmrt_dbid = MyDatabaseId;
  503.  
  504.     rtag.mmrt_relid = reln->rd_id;
  505.  
  506.     SpinAcquire(MMCacheLock);
  507.  
  508.     rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
  509.                         HASH_FIND, &found);
  510.  
  511.     if (rentry == (MMRelHashEntry *) NULL) {
  512.     SpinRelease(MMCacheLock);
  513.     elog(FATAL, "mmnblocks: rel cache hash table corrupt");
  514.     }
  515.  
  516.     if (found)
  517.     nblocks = rentry->mmrhe_nblocks;
  518.     else
  519.     nblocks = -1;
  520.  
  521.     SpinRelease(MMCacheLock);
  522.  
  523.     return (nblocks);
  524. }
  525.  
  526. /*
  527.  *  mmcommit() -- Commit a transaction.
  528.  *
  529.  *    Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
  530.  */
  531.  
  532. int
  533. mmcommit()
  534. {
  535.     return (SM_SUCCESS);
  536. }
  537.  
  538. /*
  539.  *  mmabort() -- Abort a transaction.
  540.  */
  541.  
  542. int
  543. mmabort()
  544. {
  545.     return (SM_SUCCESS);
  546. }
  547.  
  548. /*
  549.  *  MMShmemSize() -- Declare amount of shared memory we require.
  550.  *
  551.  *    The shared memory initialization code creates a block of shared
  552.  *    memory exactly big enough to hold all the structures it needs to.
  553.  *    This routine declares how much space the main memory storage
  554.  *    manager will use.
  555.  */
  556.  
  557. int
  558. MMShmemSize()
  559. {
  560.     int size;
  561.     int nbuckets;
  562.     int nsegs;
  563.     int tmp;
  564.  
  565.     /*
  566.      *  first compute space occupied by the (dbid,relid,blkno) hash table
  567.      */
  568.  
  569.     nbuckets = 1 << (int)my_log2((MMNBUFFERS - 1) / DEF_FFACTOR + 1);
  570.     nsegs = 1 << (int)my_log2((nbuckets - 1) / DEF_SEGSIZE + 1);
  571.  
  572.     size = my_log2(MMNBUFFERS) + sizeof(HHDR);
  573.     size += nsegs * DEF_SEGSIZE * sizeof(SEGMENT);
  574.     tmp = (int)ceil((double)MMNBUFFERS/BUCKET_ALLOC_INCR);
  575.     size += tmp * BUCKET_ALLOC_INCR *
  576.             (sizeof(BUCKET_INDEX) + sizeof(MMHashEntry));
  577.  
  578.     /*
  579.      *  now do the same for the rel hash table
  580.      */
  581.  
  582.     size += my_log2(MMNRELATIONS) + sizeof(HHDR);
  583.     size += nsegs * DEF_SEGSIZE * sizeof(SEGMENT);
  584.     tmp = (int)ceil((double)MMNRELATIONS/BUCKET_ALLOC_INCR);
  585.     size += tmp * BUCKET_ALLOC_INCR *
  586.             (sizeof(BUCKET_INDEX) + sizeof(MMRelHashEntry));
  587.  
  588.     /*
  589.      *  finally, add in the memory block we use directly
  590.      */
  591.  
  592.     size += (BLCKSZ * MMNBUFFERS) + sizeof(*MMCurTop) + sizeof(*MMCurRelno);
  593.     size += (MMNBUFFERS * sizeof(MMCacheTag));
  594.  
  595.     return (size);
  596. }
  597.  
  598. #endif /* MAIN_MEMORY */
  599.